package asedra.huyle.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.text.TextUtils;
import asedra.huyle.helper.DatabaseHelper;

public abstract class BaseDao<T> {
	
	protected SQLiteDatabase mDb;

	protected SQLiteOpenHelper mHelper;

	protected boolean mInTransaction;

	protected BaseDao(final Context context, final String databaseName) {
		if (mHelper == null) {
			mHelper = DatabaseHelper.getInstance(context, databaseName);
		}
		mInTransaction = false;
	}

	protected BaseDao(final SQLiteDatabase db) {
		mDb = db;
		mInTransaction = true;
	}

	protected BaseDao(final SQLiteOpenHelper helper) {
		if (mHelper == null) {
			mHelper = helper;
		}
	}

	protected int count(final String table) {
		SQLiteDatabase db = (!mInTransaction) ? mHelper.getWritableDatabase() : mDb;
		SQLiteStatement stmt = db.compileStatement("SELECT COUNT (*) FROM " + table);
		int count = (int)stmt.simpleQueryForLong();
		if(!mInTransaction)
			db.close();
		return count;
	}

	protected long delete(String tableName, ContentValues values) {
		SQLiteDatabase db = (!mInTransaction) ? mHelper.getWritableDatabase() : mDb;
		String whereClauseStr = null;
		String[] whereArgs = null;
		if (values != null) {
			final List<String> whereClause = new ArrayList<String>(values.size());
			whereArgs = new String[values.size()];
			int index = 0;
			for (final Entry<String, Object> set : values.valueSet()) {
				whereClause.add(set.getKey() + "=?");
				whereArgs[index++] = set.getValue().toString();
			}
			whereClauseStr = TextUtils.join(" AND ", whereClause);
		} else {
			whereClauseStr = "1";
		}
		long count = db.delete(tableName, whereClauseStr, whereArgs);
		if(!mInTransaction)
			db.close();
		return count;
	}

	protected Cursor find(String[] tableNames, ContentValues values, String orderBy) {
		List<String> selections = new ArrayList<String>(values.size());
		List<String> selectionArgs = new ArrayList<String>(values.size());
		List<String> tables = new ArrayList<String>(tableNames.length);
		int index = 0;
		for (final Entry<String, Object> set : values.valueSet()) {
			selections.add(set.getKey() + "=?");
			selectionArgs.add(set.getValue().toString());
			tables.add(tableNames[index++]);
		}
		String selection = TextUtils.join(" AND ", selections);
		String fromTables = TextUtils.join(", ", tables);
		String sql = "SELECT * FROM " + fromTables + " WHERE " + selection;
		if(orderBy!=null)
			sql += " ORDER BY " + orderBy;
		mDb = (!mInTransaction) ? mHelper.getWritableDatabase() : mDb;
		Cursor c = mDb.rawQuery(sql, selectionArgs.toArray(new String[0]));
		if (c.moveToFirst()) {
			return c;
		}
		return null;
	}

	protected Cursor find(String tableName, ContentValues values, String orderBy) {
		List<String> selections = new ArrayList<String>(values.size());
		List<String> selectionArgs = new ArrayList<String>(values.size());
		for (final Entry<String, Object> set : values.valueSet()) {
			selections.add(set.getKey() + "=?");
			selectionArgs.add(set.getValue().toString());
		}
		String selection = TextUtils.join(" AND ", selections);
		String sql = "SELECT * FROM " + tableName + " WHERE " + selection;
		if(orderBy!=null)
			sql += " ORDER BY " + orderBy;
		mDb = (!mInTransaction) ? mHelper.getWritableDatabase() : mDb;
		Cursor c = mDb.rawQuery(sql, selectionArgs.toArray(new String[0]));
		if (c.moveToFirst()) {
			return c;
		}
		return null;
	}

	protected Cursor getAll(String tableName, String orderBy) {
		mDb = (!mInTransaction) ? mHelper.getWritableDatabase() : mDb;
		final Cursor c = mDb.query(tableName, null, null, null, null, null, orderBy);
		if (c.moveToFirst()) {
			return c;
		}
		return null;
	}

	protected long insert(String tableName, ContentValues values) {
		SQLiteDatabase db = (!mInTransaction) ? mHelper.getWritableDatabase() : mDb;
		long result = db.insert(tableName, null, values);
		if(!mInTransaction)
			db.close();
		return result;
	}

	public void releaseDatabase() {
		if(mInTransaction){
			if(mDb!=null)
				mDb.close();
			mDb = null;
			
		} else {
			if(mHelper!=null)
				mHelper.close();
			mHelper = null;
		}
	}

	protected long update(String tableName, ContentValues values, String whereClause, String[] whereArgs) {
		SQLiteDatabase db = (!mInTransaction) ? mHelper.getWritableDatabase() : mDb;
		long result = db.update(tableName, values, whereClause, whereArgs);
		if(!mInTransaction)
			db.close();
		return result;
	}
}
